/** @file    EncoderProtocolXmlQt.cpp
 *  @author  Alessandro Polo
 *  @version $Id: EncoderProtocolXmlQt.cpp 2821 2010-08-01 11:44:26Z alex $
 *  @brief
 * File containing methods for the wosh::persistence::qt::EncoderProtocolXmlQt class.
 * The header for this class can be found in EncoderProtocolXmlQt.h, check that file
 * for class description.
 ****************************************************************************/
/* Copyright (c) 2007-2010, WOSH - Wide Open Smart Home 
 * by Alessandro Polo - OpenSmartHome.com
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the OpenSmartHome.com WOSH nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY Alessandro Polo ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL Alessandro Polo BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ****************************************************************************/
 
 #include <framework/persistence/qt/EncoderProtocolXmlQt.h>
 
 #include <framework/persistence/qt/PersistenceDbXmlQt.h>

 #include <core/ObjectFactory.h>
 #include <core/Utilities.h>
 #include <core/SystemError.h>
 #include <core/FileSystem.h>
 #include <core/DataModels.h>
 #include <core/MethodsCommon.h>

 #include <QByteArray>
 #include <QFile>


namespace wosh {
 namespace persistence {
  namespace qt {


//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

 WOSH_REGISTER(wosh::persistence::qt::EncoderProtocolXmlQt, "wosh::persistence::EncoderProtocolXml", 1.01, _static_EncoderProtocolXmlQt )

EncoderProtocolXmlQt::EncoderProtocolXmlQt()
	: EncoderProtocolXml() {
	Object::setName("EncoderProtocolXmlQt" );
	Object::getURI().setName( Object::getName() );
	Log.setContext( Object::getName() );
 }

PersistenceDb* EncoderProtocolXmlQt::createDb() const {
	PersistenceDbXmlQt* db = new PersistenceDbXmlQt();
	return db;
 }

WRESULT EncoderProtocolXmlQt::saveObject( const ISerializable* object, const std::string& parameters ) {
	if ( object == NULL ) return WRET_ERR_PARAM;
	(void)parameters;
	/*
	getEncodersBase().transactionBeginRead();
	EncoderBase* enc = selectEncoder_(getEncodersBase(), object->getClassName());
	if ( enc == NULL ) {
		getEncodersBase().transactionEnd();
		return WRET_ERR_ILLEGAL_USE;
	 }
	*/
	WRESULT ret = WRET_ERR_INTERNAL;
	//enc->serializeTo(object, 
//	getEncodersBase().transactionEnd();

	return ret;
 }

WRESULT EncoderProtocolXmlQt::saveObjects( const std::vector<ISerializable*>& objects, const std::string& parameters ) {
	std::string filename = parameters;
	FilePath xmlFile;
	if ( !xmlFile.set( filename ) ) {
		Log(LOG_CRITICAL, ":saveObjects() FAILED resolving of %s", filename.c_str() );
		return WRET_ERR_PARAM;
	 }
	WRESULT ret = WRET_OK;
	Log(LOG_VERBOSE, ":saveObjects() saving %d items in %s", objects.size(), xmlFile.getPathLocal().c_str() );
	QDomDocument doc("none");
	QDomElement rootNode = doc.createElement("WOSH");
	rootNode.setAttribute("encoder-class", getClassName() );
	rootNode.setAttribute("encoder-protocol", getProtocol() );
	rootNode.setAttribute("encoder-version", QString::number(getProtocolVersion()) );
	doc.appendChild(rootNode);
	std::vector<std::string> classErrs;
	int j = 0;
	std::vector<ISerializable*>::const_iterator it;
	for ( it=objects.begin(); it != objects.end(); ++it, ++j ) {
		if ( *it == NULL ) continue;
		EncoderBaseXmlQt* enc = dynamic_cast<EncoderBaseXmlQt*>( getEncoderFor_((*it)->getClassName()) );
		if ( enc == NULL ) {
			classErrs.push_back((*it)->getClassName());
			Log(LOG_CRITICAL, ":saveObjects() Node#%d : Class not found '%s'", j, (*it)->getClassName() );
			continue;
		 }
		QDomElement cNode = doc.createElement( (*it)->getClassName() );
		WRESULT ret = enc->serializeTo( *it, doc, cNode, false );
		if ( WFAILED(ret) )
			Log(LOG_WARNING, ":saveObjects() Node#%d : %s Error ret=%d", j, (*it)->getClassName(), ret );
		else
			Log(LOG_VERBOSE, ":saveObjects() Node#%d : saved.", j );
		rootNode.appendChild( cNode );
	 }

	QFile File( xmlFile.getPathLocal().c_str() );
	if ( File.open( QIODevice::WriteOnly ) ) {
		QTextStream TextStream(&File);
		TextStream << doc.toString();
		File.close();
		ret = WRET_OK;
	 }
	else {
		wosh::SystemError::raise(this, Log, SystemError::CRITICAL, 0, "saveObjects", "FAILED#1 : Cannot write to file %s", xmlFile.getPathLocal().c_str() );
		ret = WRET_ERR_ILLEGAL_USE;
	 }

	if ( !classErrs.empty() ) {
		std::string errs = wosh::Utilities::joinVector(classErrs, "; ");
		SystemError::raise(this, Log, SystemError::CRITICAL, 0, "saveObjects", "%d ERRORS: Classes not found: %s", classErrs.size(), errs.c_str() );
		ret = WRET_ERR_INTERNAL;
	 }
	return ret;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderProtocolXmlQt::loadObjects( std::vector<ISerializable*>& objects, const std::string& parameters ) {
	FilePath xmlFile;
	std::string source_archive = parameters;
	if ( !xmlFile.set( source_archive ) ) {
		Log(LOG_CRITICAL, ":loadObjects() FAILED resolving of %s", source_archive.c_str() );
		return WRET_ERR_PARAM;
	 }
	std::vector<std::string> sourceFiles;
	if ( xmlFile.isFolder() ) {
		WRESULT ret = FileSystem::getFilesOf( xmlFile.getPathLocal(), sourceFiles, true, true, ".xml" );
		if ( WFAILED(ret) || sourceFiles.empty() ) {
			Log(LOG_CRITICAL, ":loadObjects() FAILED getting files of %s", xmlFile.getPathLocal().c_str() );
			return WRET_ERR_PARAM;
		 }
		Log(LOG_VERBOSE, ":loadObjects() parsing %d files of folder %s", sourceFiles.size(), xmlFile.getPathLocal().c_str() );
	 }
	else if ( xmlFile.isFile() ) {
		sourceFiles.push_back( xmlFile.getPathLocal() );
	 }
	else {
		Log(LOG_CRITICAL, ":loadObjects() FAILED file %s doesn't exist!", xmlFile.getPathLocal().c_str() );
		return WRET_ERR_PARAM;
	 }
	WRESULT ret = WRET_OK;
	std::string filename;
	std::vector<std::string>::iterator it;
	for ( it=sourceFiles.begin(); it!=sourceFiles.end(); ++it ) {
		filename = *it;
		QDomDocument doc("none");
		WRESULT valid = loadXmlDocument( doc, filename );
		if ( WFAILED(valid) ) {
			ret += WRET_ERR_INTERNAL;
			SystemError::raise(this, Log, SystemError::CRITICAL, 0, "loadObjects", "FAILED#1 : Cannot load document %s", filename.c_str() );
			continue;
		 }
		QDomNodeList nodesList;
//		if ( class_name == "" )
			nodesList = doc.documentElement().childNodes();
//		else
//			nodesList = doc.documentElement().elementsByTagName( class_name.c_str() );
		int nodeCount = nodesList.length();
		if ( nodeCount == 0 ) {
			Log(LOG_CRITICAL, ":loadObjects() FAILED : No items found in %s", filename.c_str() );
			continue;
		 }
		Log(LOG_VERBOSE, ":loadObjects() loading %d items in %s", nodeCount, filename.c_str() );
		std::vector<std::string> classErrs;
		std::string tagname;
		for(int j=0; j<nodeCount; j++) {
			QDomElement child = nodesList.item(j).toElement();
			if ( child.hasAttribute("classname") )
				tagname = child.attribute("classname").toLatin1().data();
			else
				tagname = child.tagName().toLatin1().data();
			if ( tagname == "" ) {
				Log(LOG_WARNING, ":loadObjects() Node#%d : Empty TagName", j );
				continue;
			 }
			EncoderBaseXmlQt* enc = dynamic_cast<EncoderBaseXmlQt*>( getEncoderFor_(tagname.c_str()) );
			if ( enc == NULL ) {
				classErrs.push_back(tagname);
				Log(LOG_CRITICAL, ":loadObjects() Node#%d : FAILED Class not found '%s'", j, tagname.c_str() );
				continue;
			 }
			ISerializable* obj = ObjectFactory::createTypeOf<ISerializable>(tagname);
			WRESULT ret = enc->deserializeFrom(obj, child);
			if ( WFAILED(ret) )
				Log(LOG_WARNING, ":loadObjects() Node#%d : %s Deserialization-Error ret=%d", j, tagname.c_str(), ret );
			else
				Log(LOG_VERBOSE, ":loadObjects() Node#%d : %s loaded.", j, tagname.c_str() );
			objects.push_back( obj );
		 }
		if ( !classErrs.empty() ) {
			std::string errs = Utilities::joinVector(classErrs, "; ");
			SystemError::raise(this, Log, SystemError::CRITICAL, 0, "loadObjects", "%d ERRORS: Classes not found: %s", classErrs.size(), errs.c_str() );
			ret += WRET_ERR_INTERNAL;
		 }
	 }
	return ret;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderProtocolXmlQt::loadXmlDocument( QDomDocument& doc, const std::string& filename ) {
	QFile file(filename.c_str());
	if ( !file.open(QIODevice::ReadOnly) ) {
		Log(LOG_CRITICAL, ":loadXmlDocument() FAILED : Can't open file: %s", filename.c_str() );
		return WRET_ERR_PARAM;
	 }
	QString errorMsg; int errorLine; int errorCol;
	if ( !doc.setContent(&file, false, &errorMsg, &errorLine, &errorCol) ) {
		file.close();
		Log(LOG_CRITICAL, ":loadXmlDocument() FAILED : Can't set contents from: %s [Error@%d,%d : %s]", filename.c_str(), errorLine, errorCol, errorMsg.toLatin1().data() );
		return WRET_ERR_PARAM;
	 }
	file.close();
	QDomElement woshNode = doc.documentElement();
	if ( woshNode.isNull() ) {
		Log(LOG_WARNING, ":loadXmlDocument() FAILED : No root node in %s", filename.c_str() );
		return WRET_ERR_INTERNAL;
	 }
	return WRET_OK;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderProtocolXmlQt::saveXmlDocument( QDomDocument& doc, const std::string& filename ) {
	QFile File( filename.c_str() );
	if ( File.open( QIODevice::WriteOnly ) ) {
		QTextStream TextStream(&File);
		TextStream << doc.toString();
		File.close();
	 }
	else 
		Log(LOG_CRITICAL, ":saveXmlDocument() can't load file %s", filename.c_str() );

	return WRET_OK;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

WRESULT EncoderProtocolXmlQt::serializeTo( const ISerializable* object, QDomDocument& doc, QDomElement& contNode, int encoder_options ) {
	if ( object == NULL ) return WRET_ERR_PARAM;
	getEncoders().transactionBeginRead();
	EncoderBaseXmlQt* enc = dynamic_cast<EncoderBaseXmlQt*>( getEncoderFor_(object->getClassName()) );
	if ( enc == NULL ) {
		printf("\nEncoderProtocolXmlQt::serializeTo(%s) missing!\n",object->getClassName() );
		getEncoders().transactionEnd();
		return WRET_ERR_ILLEGAL_USE;
	 }
	contNode.setAttribute("class", QString(object->getClassName()) );
	if ( !EncoderBase::isCompact(encoder_options) )
		contNode.setAttribute("encoder", QString(enc->getClassName()) );
	WRESULT ret = enc->serializeTo(object, doc, contNode, encoder_options);
	getEncoders().transactionEnd();
	return ret;
 }

WRESULT EncoderProtocolXmlQt::deserializeFrom( ISerializable* object, const QDomElement& contNode ) {
	if ( object == NULL ) return WRET_ERR_PARAM;
	getEncoders().transactionBeginRead();
	EncoderBaseXmlQt* enc = dynamic_cast<EncoderBaseXmlQt*>( getEncoderFor_(object->getClassName()) );
	if ( enc == NULL ) {
		printf("\nEncoderProtocolXmlQt::deserializeFrom(%s) missing!\n",object->getClassName() );
		getEncoders().transactionEnd();
		return WRET_ERR_ILLEGAL_USE;
	 }
	WRESULT ret = enc->deserializeFrom(object, contNode);
	getEncoders().transactionEnd();
	return ret;
 }

ISerializable* EncoderProtocolXmlQt::deserializeFrom( const QDomElement& contNode, WRESULT* return_code ) {
	std::string classname = ""; double version = 0.0;
	if ( contNode.hasAttribute("class") )
		classname = contNode.attribute("class").toLatin1().data();
	getEncoders().transactionBeginRead();
	EncoderBaseXmlQt* enc = dynamic_cast<EncoderBaseXmlQt*>( getEncoderFor_(classname.c_str()) );
	if ( enc == NULL ) {
		if ( return_code != NULL ) *return_code = WRET_ERR_PARAM;
		getEncoders().transactionEnd();
		return NULL;
	 }
	ISerializable* object = ObjectFactory::createTypeOf<ISerializable>(classname, version);
	if ( object == NULL ) {
		if ( return_code != NULL ) *return_code = WRET_ERR_ILLEGAL_USE;
		getEncoders().transactionEnd();
		return NULL;
	 }
	WRESULT ret = enc->deserializeFrom(object, contNode);
	getEncoders().transactionEnd();
	if ( return_code != NULL ) *return_code = ret;
	return object;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

 WOSH_REGISTER_INTERFACE(wosh::persistence::qt::EncoderBaseXmlQt, "wosh::persistence::EncoderBaseXml", 1.0, _static_EncoderBaseXmlQt )

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

int64 EncoderBaseXmlQt::serializeTo( const ISerializable* object, char* output, int64 buffer_size, int encoder_options ) {
	QDomDocument doc("none");
	QDomElement rootNode = doc.createElement( object->getClassName() );
	doc.appendChild(rootNode);
	WRESULT ret = serializeTo( object, doc, rootNode, encoder_options );
	if ( WFAILED(ret) ) return -1;
	QByteArray buffer = doc.toByteArray();
	if ( buffer.size() > buffer_size )
		return -buffer.size();
//#ifdef _MSC_VER
//	strncpy_s(output, buffer.size(), buffer.data(), _TRUNCATE );
//#else
	strncpy(output, buffer.data(), buffer.size() );
//#endif
	return buffer.size();
 }

int64 EncoderBaseXmlQt::deserializeFrom( ISerializable* object, const char* buffer, int64 buffer_size ) {
	WRESULT ret = WRET_ERR_INTERNAL;
	QDomDocument doc("none");
	QByteArray xml_data(buffer, buffer_size);
	QString errorMsg; int errorLine = 0; int errorColumn = 0;
	bool validXml = doc.setContent(xml_data, false, &errorMsg, &errorLine, &errorColumn );
	if ( !validXml ) {
		printf("\n\nXML ERROR [Line %d, col%d]:\n%s\n", errorLine, errorColumn, errorMsg.toLatin1().data());
		return -10;
	 }
	std::string tagname = std::string( doc.documentElement().tagName().toLatin1().data() );
	if ( tagname == object->getClassName() ) {
		ret = deserializeFrom( object, doc.documentElement() );
	 }
	else {
		QDomNodeList nodesList = doc.documentElement().elementsByTagName( object->getClassName() );
		if ( nodesList.length() == 0 )				 return WRET_ERR_INTERNAL;
		ret = deserializeFrom( object, nodesList.item(0).toElement() );
	 }
	if ( WFAILED(ret) )
		return -buffer_size;
	return xml_data.size();
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

void EncoderBaseXmlQt::serializeString( const std::string& field, const std::string& value, QDomDocument& doc, QDomElement& contNode, int encoder_options ) {
	if ( isCompact(encoder_options) ) {
		if ( value.empty() ) return;
		contNode.setAttribute( field.c_str(), QString(value.c_str()) );
	 }
	else {
		QDomElement newNode = doc.createElement( field.c_str() );
		newNode.appendChild( doc.createTextNode( value.c_str() ) );
		contNode.appendChild(newNode);
	 }
 }

void EncoderBaseXmlQt::serializeLong( const std::string& field, long value, QDomDocument& doc, QDomElement& contNode, int encoder_options ) {
	if ( isCompact(encoder_options) ) {
		contNode.setAttribute( field.c_str(), (qlonglong)value );
	 }
	else {
		QDomElement newNode = doc.createElement( field.c_str() );
		newNode.appendChild( doc.createTextNode( QString::number(value) ) );
		contNode.appendChild(newNode);
	 }
 }

void EncoderBaseXmlQt::serializeDouble( const std::string& field, double value, QDomDocument& doc, QDomElement& contNode, int encoder_options ) {
	if ( isCompact(encoder_options) ) {
		contNode.setAttribute( field.c_str(), value );
	 }
	else {
		QDomElement newNode = doc.createElement( field.c_str() );
		newNode.appendChild( doc.createTextNode( QString::number(value) ) );
		contNode.appendChild(newNode);
	 }
 }

void EncoderBaseXmlQt::serializeBool( const std::string& field, bool value, QDomDocument& doc, QDomElement& contNode, int encoder_options ) {
	if ( isCompact(encoder_options) ) {
		contNode.setAttribute( field.c_str(), (int)value );
	 }
	else {
		QDomElement newNode = doc.createElement( field.c_str() );
		newNode.appendChild( doc.createTextNode( QString(Utilities::toString(value).c_str())) );
		contNode.appendChild(newNode);
	 }
 }

void EncoderBaseXmlQt::serializeInt64( const std::string& field, int64 value, QDomDocument& doc, QDomElement& contNode, int encoder_options ) {
	if ( isCompact(encoder_options) ) {
		contNode.setAttribute( field.c_str(), (qlonglong)value );
	 }
	else {
		QDomElement newNode = doc.createElement( field.c_str() );
		newNode.appendChild( doc.createTextNode( QString::number(value)) );
		contNode.appendChild(newNode);
	 }
 }

void EncoderBaseXmlQt::serializeFloat( const std::string& field, float value, QDomDocument& doc, QDomElement& contNode, int encoder_options ) {
	if ( isCompact(encoder_options) ) {
		contNode.setAttribute( field.c_str(), value );
	 }
	else {
		QDomElement newNode = doc.createElement( field.c_str() );
		newNode.appendChild( doc.createTextNode( QString::number(value) ) );
		contNode.appendChild(newNode);
	 }
 }

void EncoderBaseXmlQt::serializeVectorString( const std::vector<std::string>& dataset, QDomDocument& doc, QDomElement& contNode, int encoder_options, const std::string& tagname ) {
	if ( !isCompact(encoder_options) )
		EncoderBaseXmlQt::serializeLong( "size", dataset.size(), doc, contNode, true );
	std::vector<std::string>::const_iterator it;
	const std::vector<std::string>::const_iterator it_end = dataset.end();
	for ( it=dataset.begin(); it!=it_end; ++it ) {
		QDomElement itemNode = doc.createElement( tagname.c_str() ); contNode.appendChild(itemNode);
		if ( isCompact(encoder_options) )
			itemNode.setAttribute( "value", (*it).c_str() );
		else
			itemNode.appendChild( doc.createTextNode( (*it).c_str() ) );
	 }
 }

void EncoderBaseXmlQt::serializeMapStringLong( const std::map<std::string, long>& dataset, QDomDocument& doc, QDomElement& contNode, int encoder_options, const std::string& tagname, const std::string& value_fieldname ) {
	if ( !isCompact(encoder_options) )
		EncoderBaseXmlQt::serializeLong( "size", dataset.size(), doc, contNode, true );
	std::map<std::string, long>::const_iterator it;
	const std::map<std::string, long>::const_iterator it_end = dataset.end();
	for ( it=dataset.begin(); it!=it_end; ++it ) {
		QDomElement itemNode;
		if ( tagname.empty() )
			itemNode = doc.createElement( it->first.c_str() );
		else {
			itemNode = doc.createElement( tagname.c_str() );
			itemNode.setAttribute( "key", it->first.c_str() );
		 }
		contNode.appendChild(itemNode);
		if ( isCompact(encoder_options) )
			itemNode.setAttribute( value_fieldname.c_str(), (qlonglong)it->second );
		else
			itemNode.appendChild( doc.createTextNode( QString::number(it->second) ) );
	 }
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

std::string EncoderBaseXmlQt::deserializeString( const std::string& field, const std::string& default_value, const QDomElement& contNode, bool* valid ) {
	if ( valid != NULL ) *valid = true;
	if ( contNode.hasAttribute( field.c_str() ) )
		return std::string( contNode.attribute( field.c_str() ).toLatin1().data() );
	QDomElement vNode = contNode.namedItem( field.c_str() ).toElement();
	if ( !vNode.isNull() )
		return std::string( vNode.text().toLatin1().data() );
	if ( valid != NULL ) *valid = false;
	return default_value;
 }

long EncoderBaseXmlQt::deserializeLong( const std::string& field, long default_value, const QDomElement& contNode, bool* valid ) {
	if ( contNode.hasAttribute( field.c_str() ) )
		return contNode.attribute( field.c_str() ).toLong(valid);
	QDomElement vNode = contNode.namedItem( field.c_str() ).toElement();
	if ( !vNode.isNull() )
		return vNode.text().toLong(valid);
	return default_value;
 }

double EncoderBaseXmlQt::deserializeDouble( const std::string& field, double default_value, const QDomElement& contNode, bool* valid ) {
	if ( contNode.hasAttribute( field.c_str() ) )
		return contNode.attribute( field.c_str() ).toDouble(valid);
	QDomElement vNode = contNode.namedItem( field.c_str() ).toElement();
	if ( !vNode.isNull() )
		return vNode.text().toDouble(valid);
	return default_value;
 }

bool EncoderBaseXmlQt::deserializeBool( const std::string& field, bool default_value, const QDomElement& contNode, bool* valid ) {
	if ( contNode.hasAttribute( field.c_str() ) ) {
		if ( valid != NULL ) *valid = true;
		return Utilities::fromString( std::string( contNode.attribute( field.c_str() ).toLatin1().data() ), default_value);
	 }
	QDomElement vNode = contNode.namedItem( field.c_str() ).toElement();
	if ( !vNode.isNull() ) {
		if ( valid != NULL ) *valid = true;
		return Utilities::fromString( std::string( vNode.text().toLatin1().data() ), default_value);
	 }
	if ( valid != NULL ) *valid = false;
	return default_value;
 }

int64 EncoderBaseXmlQt::deserializeInt64( const std::string& field, int64 default_value, const QDomElement& contNode, bool* valid ) {
	if ( contNode.hasAttribute( field.c_str() ) )
		return contNode.attribute( field.c_str() ).toLongLong(valid);
	QDomElement vNode = contNode.namedItem( field.c_str() ).toElement();
	if ( !vNode.isNull() )
		return vNode.text().toLongLong(valid);
	return default_value;
 }

float EncoderBaseXmlQt::deserializeFloat( const std::string& field, float default_value, const QDomElement& contNode, bool* valid ) {
	if ( contNode.hasAttribute( field.c_str() ) )
		return contNode.attribute( field.c_str() ).toFloat(valid);
	QDomElement vNode = contNode.namedItem( field.c_str() ).toElement();
	if ( !vNode.isNull() )
		return vNode.text().toFloat(valid);
	return default_value;
 }

int EncoderBaseXmlQt::deserializeVectorString( std::vector<std::string>& dataset, const QDomElement& contNode, const std::string& tagname, bool* valid ) {
	int count = 0;
	QDomNodeList nodesList = contNode.childNodes();
	for( unsigned int j=0; j<nodesList.length(); ++j ) {
		QDomElement childNode = nodesList.item(j).toElement();
		if ( !tagname.empty() && childNode.tagName() != tagname.c_str() ) continue;
		if ( childNode.isNull() ) continue;
		if ( !childNode.text().isEmpty() )
			dataset.push_back( childNode.text().toLatin1().data() );
		else if ( childNode.hasAttribute( "value" ) )
			dataset.push_back( childNode.text().toLatin1().data() );
		else continue;
		++count;
	 }
	if ( valid != NULL ) *valid = true;
	return count;
 }

int EncoderBaseXmlQt::deserializeMapStringLong( std::map<std::string, long>& dataset, const QDomElement& contNode, const std::string& tagname, const std::string& value_fieldname, bool* valid ) {
	int count = 0;
	QDomNodeList nodesList = contNode.childNodes();
	for( unsigned int j=0; j<nodesList.length(); ++j ) {
		QDomElement childNode = nodesList.item(j).toElement();
		if ( !tagname.empty() && childNode.tagName() != tagname.c_str() ) continue;
		if ( childNode.isNull() ) continue;

		std::string field = "";
		long value = 0;
		if ( value_fieldname.empty() && !childNode.text().isEmpty() )
			value = childNode.text().toLong();
		else if ( !value_fieldname.empty() && childNode.hasAttribute( value_fieldname.c_str() ) )
			value = childNode.attribute( value_fieldname.c_str() ).toLong();
		else
			continue;

		if ( tagname.empty() )
			field = childNode.tagName().toLatin1().data();
		else if ( childNode.hasAttribute( "key" ) )
			field = childNode.attribute("key").toLatin1().data();
		else
			continue;

		dataset[field] = value;
		++count;
	 }
	if ( valid != NULL ) *valid = true;
	return count;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

  }; // namespace qt
 }; // namespace persistence
}; // namespace wosh
